﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
using Runda.CMS.Common.Entity;
using Runda.CMS.Bll;
using Runda.CMS.Common.Utility;

namespace Runda.CMS.Workflow
{
    public class WorkflowInstance:IWorkflowInstance
    {
        public WorkflowInstance(Guid modelID,SysUserEntity UserEntity)
        {
            CurrentUserEntity = UserEntity;
            InitBll();
            this.ModelID = modelID;
        }

        public WorkflowInstance(Guid InstanceRoutingID,Guid TaskID, SysUserEntity UserEntity)
        {
            CurrentUserEntity = UserEntity;
            InitBll();
            this.InstanceRoutingID = InstanceRoutingID;
            this.TaskID = TaskID; 
        }
   
        private WflActivityBll ActivityBll;
        private WflInstanceBll InstanceBll;
        private WflInstanceRoutingBll InstanceRoutingBll;
        private WflRoutingBll RoutingBll;
        private WflTaskBll TaskBll;
        private WflCommentBll CommentBll;

        #region Property 
        private SysUserEntity CurrentUserEntity { set; get; }

        private Guid ModelID { get; set; }

        private Guid InstanceRoutingID{ get;set;}

        private Guid TaskID { get; set; }

        public WflInstanceEntity InstanceEntity { get; internal set; }
        #endregion

        #region IWorkflowInstance Members

        public event EventHandler<RoutingEventArgs> OnNextRouting;

        public void Start(Guid BusinessID,string DisplayMsg)
        {
            //获取当前Model的开始节点
            WflActivityEntity FirstActivity = ActivityBll.Get<WflActivityEntity>(" and ModelID='"+ModelID+"' and ActivityType=1 and Isnull(deleted,0) = 0 ");
            WflRoutingEntity CurrentRouting = RoutingBll.Get<WflRoutingEntity>(" and ActivityID = '"+FirstActivity.ActivityID+"'");
            //保存流程实例
            InstanceEntity = new WflInstanceEntity();
            InstanceEntity.ModelID = ModelID;
            InstanceEntity.InstanceName = string.Empty;
            InstanceEntity.CreatedBy = CurrentUserEntity.UserID;
            InstanceEntity.CreatedAt = DateTime.Now;
            InstanceEntity.BussinessID = BusinessID;
            InstanceBll.Insert(InstanceEntity);
            //保存当前Routing
            WflInstanceRoutingEntity TrackEntity = new WflInstanceRoutingEntity();
            TrackEntity.TrackID = Guid.NewGuid();
            TrackEntity.InstanceID = InstanceEntity.InstanceID;
            TrackEntity.ActivityID = FirstActivity.ActivityID;
            TrackEntity.NextActivityID = CurrentRouting.NextActivityID;
            TrackEntity.CheckBy = CurrentUserEntity.UserID;
            TrackEntity.CheckName = CurrentUserEntity.UserName;
            TrackEntity.CheckStatus = (byte)ActivityStatus.Submit;
            TrackEntity.CheckDate = DateTime.Now;
            InstanceRoutingBll.Insert(TrackEntity);
            //保存下一级的审批信息
            if (CurrentRouting.NextActivityID != Guid.Empty)
            {
                WflRoutingEntity NextRouting = RoutingBll.Get<WflRoutingEntity>(" and ActivityID = '" + CurrentRouting.NextActivityID + "' and Isnull(deleted,0) = 0 ");

                WflInstanceRoutingEntity NextTrackEntity = new WflInstanceRoutingEntity();
                NextTrackEntity.TrackID = Guid.NewGuid();
                NextTrackEntity.InstanceID = InstanceEntity.InstanceID;
                NextTrackEntity.ActivityID = NextRouting.ActivityID;
                NextTrackEntity.NextActivityID = NextRouting.NextActivityID;
                NextTrackEntity.CheckBy = Guid.Empty;
                NextTrackEntity.CheckName = string.Empty;
                NextTrackEntity.CheckStatus = (byte)ActivityStatus.Wait;
                InstanceRoutingBll.Insert(NextTrackEntity);
                //AddTask(string.Format( "您有从[{0}]提交的[{1}]阶段工作待完成。",CurrentUserEntity.UserName ,FirstActivity.ActivityName),"&BussinessID="+BusinessID.ToString(), NextTrackEntity);
                AddTask(string.Format("您有从[{0}]提交的[{1}]阶段工作待完成。", CurrentUserEntity.UserName, DisplayMsg), "&BussinessID=" + BusinessID.ToString(), NextTrackEntity);
            }
            RaiseOnNextRoutingEvent(new RoutingEventArgs(CurrentRouting,InstanceEntity.InstanceID));
        }

        public void ReStart(Guid InstanceID)
        {
            //获取当前开始节点
            WflInstanceEntity InstanceEntity = new WflInstanceBll().Get < WflInstanceEntity>(InstanceID);

            WflActivityEntity FirstActivity = ActivityBll.Get<WflActivityEntity>(" and ModelID='" + InstanceEntity.ModelID + "' and ActivityType=1 and Isnull(deleted,0) = 0 ");
            WflRoutingEntity CurrentRouting = RoutingBll.Get<WflRoutingEntity>(" and ActivityID = '" + FirstActivity.ActivityID + "' and Isnull(deleted,0) = 0 ");

            //保存当前Routing
            WflInstanceRoutingEntity TrackEntity = new WflInstanceRoutingEntity();
            TrackEntity.TrackID = Guid.NewGuid();
            TrackEntity.InstanceID = InstanceID;
            TrackEntity.ActivityID = FirstActivity.ActivityID;
            TrackEntity.NextActivityID = CurrentRouting.NextActivityID;
            TrackEntity.CheckBy = CurrentUserEntity.UserID;
            TrackEntity.CheckName = CurrentUserEntity.UserName;
            TrackEntity.CheckStatus = (byte)ActivityStatus.Submit;
            TrackEntity.CheckDate = DateTime.Now;
            InstanceRoutingBll.Insert(TrackEntity); 

            //保存下一级的审批信息
            if (CurrentRouting.NextActivityID != Guid.Empty)
            {
                WflRoutingEntity NextRouting = RoutingBll.Get<WflRoutingEntity>(" and ActivityID = '" + CurrentRouting.NextActivityID + "' and Isnull(deleted,0) = 0 ");

                WflInstanceRoutingEntity NextTrackEntity = new WflInstanceRoutingEntity();
                NextTrackEntity.TrackID = Guid.NewGuid();
                NextTrackEntity.InstanceID = InstanceEntity.InstanceID;
                NextTrackEntity.ActivityID = NextRouting.ActivityID;
                NextTrackEntity.NextActivityID = NextRouting.NextActivityID;
                NextTrackEntity.CheckBy = Guid.Empty;
                NextTrackEntity.CheckName = string.Empty;
                NextTrackEntity.CheckStatus = (byte)ActivityStatus.Wait;
                InstanceRoutingBll.Insert(NextTrackEntity);
                AddTask(string.Format("您有[从[{0}]过来的[{1}]阶段工作待完成。", CurrentUserEntity.UserName, FirstActivity.ActivityName), "&BussinessID=" + InstanceEntity.BussinessID.ToString(), NextTrackEntity); 
            }
            RaiseOnNextRoutingEvent(new RoutingEventArgs(CurrentRouting, InstanceEntity.InstanceID));
        }

        public void Approve(string Comment)
        {
            //更新当前Routing的状态
            WflInstanceRoutingEntity TrackEntity = InstanceRoutingBll.Get<WflInstanceRoutingEntity>(InstanceRoutingID);

            WflRoutingEntity CurrentRouting = RoutingBll.Get<WflRoutingEntity>(" and ActivityID = '" + TrackEntity.ActivityID + "' and Isnull(deleted,0) = 0 ");
            WflActivityEntity CurrentActivity = ActivityBll.Get<WflActivityEntity>(TrackEntity.ActivityID);

            InstanceEntity = InstanceBll.Get<WflInstanceEntity>(TrackEntity.InstanceID);

            if (CurrentRouting.NextActivityID == Guid.Empty)
            {
                TrackEntity.CheckBy = CurrentUserEntity.UserID;
                TrackEntity.CheckName = CurrentUserEntity.UserName; 
                TrackEntity.CheckDate = DateTime.Now;
                TrackEntity.CheckStatus = (byte)ActivityStatus.Complate;
                TrackEntity.Comment = Comment;
            }
            else
            {
                TrackEntity.CheckBy = CurrentUserEntity.UserID;
                TrackEntity.CheckName = CurrentUserEntity.UserName;
                TrackEntity.CheckDate = DateTime.Now;
                TrackEntity.CheckStatus = (byte)ActivityStatus.Approve;
                TrackEntity.Comment = Comment;
            }
            InstanceRoutingBll.Update(TrackEntity);
            //更新Task
            WflTaskEntity ProviousTask = TaskBll.Get<WflTaskEntity>(TaskID);
            ProviousTask.Status = 1;
            TaskBll.Update(ProviousTask);
            //保存下一级的审批信息
            if (CurrentRouting.NextActivityID != Guid.Empty)
            {
                WflRoutingEntity NextRouting = RoutingBll.Get<WflRoutingEntity>(" and ActivityID = '" + CurrentRouting.NextActivityID + "' and Isnull(deleted,0) = 0 ");

                WflInstanceRoutingEntity NextTrackEntity = new WflInstanceRoutingEntity();
                NextTrackEntity.TrackID = Guid.NewGuid();
                NextTrackEntity.InstanceID = TrackEntity.InstanceID;
                NextTrackEntity.ActivityID = NextRouting.ActivityID;
                NextTrackEntity.NextActivityID = NextRouting.NextActivityID;
                NextTrackEntity.CheckBy = Guid.Empty;
                NextTrackEntity.CheckName = string.Empty;
                NextTrackEntity.CheckStatus = (byte)ActivityStatus.Wait;
                InstanceRoutingBll.Insert(NextTrackEntity);
                AddTask(string.Format("您有[从[{0}]过来的[{1}]阶段工作待完成。", CurrentUserEntity.UserName, CurrentActivity.ActivityName), "&BussinessID=" + InstanceEntity.BussinessID.ToString(), NextTrackEntity); 
            }
            RaiseOnNextRoutingEvent(new RoutingEventArgs(CurrentRouting, TrackEntity.InstanceID));
        }

        public void Reject( string Comment)
        {
            //更新当前Routing的状态
            WflInstanceRoutingEntity TrackEntity = InstanceRoutingBll.Get<WflInstanceRoutingEntity>(InstanceRoutingID);

            WflRoutingEntity CurrentRouting = RoutingBll.Get<WflRoutingEntity>(" and ActivityID = '" + TrackEntity.ActivityID + "' and Isnull(deleted,0) = 0 ");

            TrackEntity.CheckBy = CurrentUserEntity.UserID;
            TrackEntity.CheckName = CurrentUserEntity.UserName;
            TrackEntity.CheckDate = DateTime.Now;
            TrackEntity.CheckStatus = (byte)ActivityStatus.Reject;
            TrackEntity.Comment = Comment;
            InstanceRoutingBll.Update(TrackEntity);

            WflTaskEntity ProviousTask = TaskBll.Get<WflTaskEntity>(TaskID);
            ProviousTask.Status = 1;
            TaskBll.Update(ProviousTask);

            RaiseOnNextRoutingEvent(new RoutingEventArgs(CurrentRouting, TrackEntity.InstanceID));
        }

        public void Comment(Guid CommentID,string Comment)
        {
            WflInstanceRoutingEntity TrackEntity = InstanceRoutingBll.Get<WflInstanceRoutingEntity>(InstanceRoutingID);

            WflCommentEntity commentEntity = CommentBll.Get<WflCommentEntity>(CommentID);
            if (commentEntity == null)
            {
                return;
                commentEntity = new WflCommentEntity();
                commentEntity.CreatedAt = DateTime.Now;
                commentEntity.InstanceID = TrackEntity.InstanceID;
                commentEntity.ActivityID = TrackEntity.ActivityID;
            }
            commentEntity.Comments = Comment;
            commentEntity.CommentStatus = (byte)Enumerator.ContractCommentStatus.Write;
            commentEntity.CommentAt = DateTime.Now;
            //commentEntity.LeaderID = CurrentUserEntity.UserID;
            CommentBll.InsertOrUpdate(commentEntity);  
            
            //更新Task
            WflTaskEntity taskentity = TaskBll.Get<WflTaskEntity>(TaskID);
            taskentity.Status = 1;
            TaskBll.Update(taskentity);
        }
        #endregion

        #region private methods

        private void RaiseOnNextRoutingEvent(RoutingEventArgs e)
        {
            if (OnNextRouting != null)
                OnNextRouting(this, e);
        }

        private void InitBll()
        {
            ActivityBll = new WflActivityBll();
            InstanceBll = new WflInstanceBll();
            InstanceRoutingBll = new WflInstanceRoutingBll();
            RoutingBll = new WflRoutingBll();
            TaskBll = new WflTaskBll();
            CommentBll = new WflCommentBll();
        }

        public void AddTask(string Title,string BussinessParm, WflInstanceRoutingEntity NextRoutingEntity)
        {
            WflActivityEntity NextActivityEntity = ActivityBll.Get<WflActivityEntity>(" and ActivityID = '" + NextRoutingEntity.ActivityID + "'");
            WflTaskEntity taskEntity = new WflTaskEntity();
            taskEntity.TaskID = Guid.NewGuid();
            taskEntity.Title = Title;
            taskEntity.Entry = String.Concat(NextActivityEntity.ActivityEntry, NextActivityEntity.ActivityEntry.IndexOf('?') == -1 ? "?" : "&", "TrackID=", NextRoutingEntity.TrackID, "&TaskID=", taskEntity.TaskID, BussinessParm);
            taskEntity.ActivityID = NextActivityEntity.ActivityID;
            taskEntity.Status = 0;
            taskEntity.TaskType = 0;
            TaskBll.Insert(taskEntity);

            List<WflActivityCheckersEntity> Checkers = new WflActivityCheckersBll().GetAll<WflActivityCheckersEntity>(" and ActivityID = '"+NextActivityEntity.ActivityID+"'");
            WflTaskUserBll tuBll = new WflTaskUserBll();
            foreach (WflActivityCheckersEntity check in Checkers)
            {
                WflTaskUserEntity tuEntity = new WflTaskUserEntity();
                tuEntity.ID = Guid.NewGuid();
                tuEntity.TaskID = taskEntity.TaskID;
                tuEntity.UserID = check.UserID;
                tuEntity.CreatedAt = DateTime.Now;
                tuBll.Insert(tuEntity);
            }
        }

        #endregion
    }
}
